package com.jlkf.service.util;

import java.beans.BeanInfo;
import java.beans.IntrospectionException;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.net.InetAddress;
import java.text.SimpleDateFormat;
import java.util.Arrays;
import java.util.Calendar;
import java.util.Collections;
import java.util.Comparator;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Random;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;

import net.sf.json.JSONObject;

/**
 * 字符串工具类
 *
 */
public class StringTools {

	private static Logger log = LoggerFactory.getLogger(StringTools.class);

	/**
	 * 获取当前容器的根目录，如jboss则结果为/data/jboss4.2.3GA/，如tomcat则为/data/tomcat7/
	 * 
	 * @return
	 */
	public static String getContainerPath() {
		// jboss结果为其bin目录如/data/jboss.4.2.3.GA/bin，tomcat则结果为其根目录如/data/tomcat7
		String containerBinPath = System.getProperty("user.dir");
		System.out.println("system property [user.dir] = " + containerBinPath);
		// 把windows路径中的\替换为linux路径的/
		containerBinPath = containerBinPath.replaceAll("\\\\", "/");
		if (containerBinPath.contains("/bin")) {
			return containerBinPath.substring(0, containerBinPath.indexOf("/bin"));
		} else {
			return containerBinPath;
		}
	}

	/**
	 * 字符串首字母大写转换
	 * 
	 * @return
	 */
	public static String firstCharUp(String str) {
		if (isNull(str)) {
			return "";
		}
		try {
			char[] cs = str.toCharArray();
			// 首字母大写，并且首字母是小写才转。
			if (cs[0] > 96) {
				cs[0] -= 32;
			}
			return String.valueOf(cs);
		} catch (Exception e) {
			log.error("首字母大写转换出错", e);
		}
		return "";
	}

	/**
	 * obj转换为json字符串，同时忽略空属性，即只输出非空属性。
	 * 
	 * @param obj
	 * @return
	 */
	public static String obj2Json(final Object obj) {
		if (obj == null) {
			return "";
		}
		try {
			ObjectMapper mapper = new ObjectMapper();
			mapper.disable(SerializationFeature.FAIL_ON_EMPTY_BEANS);
			return mapper.writeValueAsString(obj);
		} catch (Exception e) {
			log.error(e.getMessage(), e);
		}
		return "";
	}

	/**
	 * json字符串转换为对象，需要指定class。
	 * 
	 * @param json
	 * @param clazz
	 * @return
	 */
	public static <T> T json2Obj(String json, Class<T> clazz) {
		if (isNull(json)) {
			return null;
		}
		try {
			ObjectMapper mapper = new ObjectMapper();
			return mapper.readValue(json, clazz);
		} catch (Exception e) {
			log.error(e.getMessage(), e);
		}
		return null;
	}

	/**
	 * 取得本应用所在机器的ip
	 * 
	 * @return
	 */
	public static String getCurrentIp() {
		String ip = "";
		try {
			InetAddress addr = InetAddress.getLocalHost();
			ip = addr.getHostAddress();// 获得本机IP
		} catch (Exception e) {
			log.error(e.getMessage(), e);
		}
		return ip;
	}

	/**
	 * 判断字符串是否为空或空白串。
	 * 
	 * @param str
	 * @return 若字符串为null或空白串返回true
	 */
	public static boolean isNull(String str) {
		return str == null || str.trim().length() < 1;
	}

	/**
	 * 生成length位的随机字符串
	 * 
	 * @return
	 */
	public static String createNoncestr(int length) {
		String chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
		String res = "";
		for (int i = 0; i < length; i++) {
			Random rd = new Random();
			res += chars.charAt(rd.nextInt(chars.length() - 1));
		}
		return res;
	}

	/**
	 * string TO List
	 * 
	 * @param str
	 *            ; 以（隔开符）隔开的一串字符串
	 * @param delimit
	 *            隔开符
	 * @return
	 */
	public static List<String> StringToList(String str, String delimit) {

		if (null != str && !"".equals(str)) {

			String[] strArray = str.split(delimit);
			List<String> strList = Arrays.asList(strArray);
			return strList;
		}

		return null;
	}

	/**
	 * 判断字符串是否为空或者空字符串
	 * 
	 * @param str
	 * @return
	 */
	public static boolean isEmpty(String str) {
		return null == str || str.trim().isEmpty();
	}

	/**
	 * 判断数组中的字符串是否全部为空。true全部为空，false至少有一个不为空。
	 * 
	 * @param str
	 * @return
	 */
	public static boolean isEmptyAll(String... str) {
		if (str == null || str.length < 1) {
			return true;
		}
		for (String one : str) {
			if (!isEmpty(one)) {
				return false;
			}
		}
		return true;
	}

	/**
	 * 判断数组中的字符串是否有一个为空。true有一个为空，false全部非空。
	 * 
	 * @param str
	 * @return
	 */
	public static boolean isEmptyOne(String... str) {
		if (str == null || str.length < 1) {
			return true;
		}
		for (String one : str) {
			if (isEmpty(one)) {
				return true;
			}
		}
		return false;
	}

	/**
	 * 连续空白字符替换为一个空格
	 * 
	 * @param str
	 * @return
	 */
	public static String getStringOneBlank(String str) {
		if (!isEmpty(str)) {
			Pattern p = Pattern.compile("\\s+");
			Matcher m = p.matcher(str);
			String strNoBlank = m.replaceAll(" ");
			return strNoBlank;
		} else {
			return str;
		}
	}

	public static String getClassAndMethod(String clazz) {
		if (isEmpty(clazz) || !clazz.contains(".")) {
			return "";
		}
		try {
			int index = clazz.lastIndexOf(".");// 最后一个.
			String tmp = clazz.substring(0, index - 1);// 倒数第二个.
			index = tmp.lastIndexOf(".");
			return clazz.substring(index + 1);// 取类名.方法名的字符串，如“EmployeeMapper.selectByPrimaryKey”
		} catch (Exception e) {
			log.error("", e);
		}
		return "";
	}

	/**
	 * 判断字符串是否是整数
	 *
	 * @author freddy
	 * @param number
	 * @return
	 */
	public static boolean isInteger(String number) {
		boolean isNumber = false;
		if (number == null) {
			return false;
		}
		if (!StringTools.isEmpty(number.trim())) {
			isNumber = number.matches("^([1-9]\\d*)|(0)$");
		}
		return isNumber;
	}

	/**
	 * 将一个 Map 对象转化为一个 JavaBean
	 * 
	 * @param type
	 *            要转化的类型
	 * @param map
	 *            包含属性值的 map
	 * @return 转化出来的 JavaBean 对象
	 * @throws IntrospectionException
	 *             如果分析类属性失败
	 * @throws IllegalAccessException
	 *             如果实例化 JavaBean 失败
	 * @throws InstantiationException
	 *             如果实例化 JavaBean 失败
	 * @throws InvocationTargetException
	 *             如果调用属性的 setter 方法失败
	 */
	@SuppressWarnings("rawtypes")
	public static Object mapToBean(Class type, Map map)
			throws IntrospectionException, IllegalAccessException, InstantiationException, InvocationTargetException {
		BeanInfo beanInfo = Introspector.getBeanInfo(type); // 获取类属性
		Object obj = type.newInstance(); // 创建 JavaBean 对象

		// 给 JavaBean 对象的属性赋值
		PropertyDescriptor[] propertyDescriptors = beanInfo.getPropertyDescriptors();
		for (int i = 0; i < propertyDescriptors.length; i++) {
			PropertyDescriptor descriptor = propertyDescriptors[i];
			String propertyName = descriptor.getName();

			if (map.containsKey(propertyName)) {
				// 下面一句可以 try 起来，这样当一个属性赋值失败的时候就不会影响其他属性赋值。
				Object value = map.get(propertyName);

				Object[] args = new Object[1];
				args[0] = value;

				descriptor.getWriteMethod().invoke(obj, args);
			}
		}
		return obj;
	}

	/**
	 * 将一个 JavaBean 对象转化为一个 Map
	 * 
	 * @param bean
	 *            要转化的JavaBean 对象
	 * @return 转化出来的 Map 对象
	 * @throws IntrospectionException
	 *             如果分析类属性失败
	 * @throws IllegalAccessException
	 *             如果实例化 JavaBean 失败
	 * @throws InvocationTargetException
	 *             如果调用属性的 setter 方法失败
	 */
	@SuppressWarnings({ "rawtypes", "unchecked" })
	public static Map beanToMap(Object bean)
			throws IntrospectionException, IllegalAccessException, InvocationTargetException {
		Class type = bean.getClass();
		Map returnMap = new HashMap();
		BeanInfo beanInfo = Introspector.getBeanInfo(type);

		PropertyDescriptor[] propertyDescriptors = beanInfo.getPropertyDescriptors();
		for (int i = 0; i < propertyDescriptors.length; i++) {
			PropertyDescriptor descriptor = propertyDescriptors[i];
			String propertyName = descriptor.getName();
			if (!propertyName.equals("class")) {
				Method readMethod = descriptor.getReadMethod();
				Object result = readMethod.invoke(bean, new Object[0]);
				if (result != null) {
					returnMap.put(propertyName, result);
				} else {
					returnMap.put(propertyName, "");
				}
			}
		}
		return returnMap;
	}

	/**
	 * 检查字符串是否是邮箱格式
	 * 
	 * @param email
	 * @return
	 */
	public static boolean isEmail(String email) {
		// 正则表达式
		/*
		 * String regex = "^[A-Za-z]{1,40}@[A-Za-z0-9]{1,40}\\.[A-Za-z]{2,3}$";
		 * return email.matches(regex);
		 */

		// 不适用正则
		if (email == null || "".equals(email))
			return false;
		if (!containsOneWord('@', email) || !containsOneWord('.', email))
			return false;
		String prefix = email.substring(0, email.indexOf("@"));
		String middle = email.substring(email.indexOf("@") + 1, email.indexOf("."));
		String subfix = email.substring(email.indexOf(".") + 1);
		System.out.println("prefix=" + prefix + "  middle=" + middle + "  subfix=" + subfix);

		if (prefix == null || prefix.length() > 40 || prefix.length() == 0)
			return false;
		if (!isAllWordsAndNo(prefix))
			return false;
		if (middle == null || middle.length() > 40 || middle.length() == 0)
			return false;
		if (!isAllWordsAndNo(middle))
			return false;
		if (subfix == null || subfix.length() > 3 || subfix.length() < 2)
			return false;
		if (!isAllWords(subfix))
			return false;
		return true;
	}

	// 判断字符串只包含指定的一个字符c
	private static boolean containsOneWord(char c, String word) {
		char[] array = word.toCharArray();
		int count = 0;
		for (Character ch : array) {
			if (c == ch) {
				count++;
			}
		}
		return count == 1;
	}

	// 检查一个字符串是否全部是字母
	private static boolean isAllWords(String prefix) {
		char[] array = prefix.toCharArray();
		for (Character ch : array) {
			if (ch < 'A' || ch > 'z' || (ch < 'a' && ch > 'Z'))
				return false;
		}
		return true;
	}

	// 检查一个字符串是否包含字母和数字
	private static boolean isAllWordsAndNo(String middle) {
		char[] array = middle.toCharArray();
		for (Character ch : array) {
			if (ch < '0' || ch > 'z')
				return false;
			else if (ch > '9' && ch < 'A')
				return false;
			else if (ch > 'Z' && ch < 'a')
				return false;
		}
		return true;
	}

	/*
	 * 判断是否是大于0的整数
	 */
	public static boolean numIsGT0(String number) {
		if (isInteger(number) && Integer.valueOf(number.trim()) >= 0) {
			return true;
		}
		return false;
	}

	public static boolean numIsGT1(String number) {
		if (isInteger(number) && Integer.valueOf(number.trim()) > 0) {
			return true;
		}
		return false;
	}

	public static boolean numIsGT0Short(String number) {
		if (isInteger(number) && Integer.valueOf(number.trim()) >= 0
				&& Integer.valueOf(number.trim()) <= Short.MAX_VALUE) {
			return true;
		}
		return false;
	}

	public static boolean numIsGT0Byte(String number) {
		if (isInteger(number) && Integer.valueOf(number.trim()) >= 0
				&& Integer.valueOf(number.trim()) <= Byte.MAX_VALUE) {
			return true;
		}
		return false;
	}

	@SuppressWarnings({ "rawtypes", "unchecked" })
	public static Map jsonToMap(String json) {
		Map map = new HashMap();
		JSONObject j = JSONObject.fromObject(json);
		Iterator keys = j.keys();
		while (keys.hasNext()) {
			String key = (String) keys.next();
			String value = j.get(key).toString();
			if (value.startsWith("{") && value.endsWith("}")) {
				map.put(key, jsonToMap(value));
			} else {
				map.put(key, value);
			}

		}
		return map;
	}
	
}
